package tech.yixiyun.framework.kuafu.view;

import cn.hutool.core.io.IoUtil;
import tech.yixiyun.framework.kuafu.context.ApplicationContext;

import java.io.File;
import java.io.InputStream;

/**
 * 响应输出下载文件流
 */
public class StreamView extends View {

    /**
     * 响应头
     */
    private String[] headers;

    /**
     * 输入流 。它和bytes只能二选一用
     */
    private InputStream is;

    /**
     * 字节数组。它和inputstream只能二选一用
     */
    public byte[] bytes;


    /**
     * 从一个字节数组输出一个流
     * @param bytes
     * @param headers 响应头，按照key，value的形式传入
     */
    public StreamView(byte[] bytes, String... headers) {
        this.headers = headers;
        this.bytes = bytes;
    }
    /**
     * 从一个输入流输出一个流
     * @param is
     * @param headers 响应头，按照key，value的形式传入
     */
    public StreamView(InputStream is, String... headers) {
        this.headers = headers;
        this.is = is;
    }
    /**
     * 从一个文件输出一个流
     * @param file
     * @param headers 响应头，按照key，value的形式传入
     */
    public StreamView(File file, String... headers) {
        this.headers = headers;
        this.is = IoUtil.toStream(file);
    }

    /**
     * 从一个路径读取文件输出一个流
     * @param path 路径，如果以/开头，就以绝对路径解析，否则就以相对项目webapp文件夹的路径去解析
     * @param headers 响应头，按照key，value的形式传入
     */
    public StreamView(String path, String... headers) {
        this.headers = headers;
        if (path.startsWith("/")) {
            this.is = IoUtil.toStream(new File(path));
        } else {
            this.is = ApplicationContext.getServletContext().getResourceAsStream(path);
        }
    }




    @Override
    public void render() {
        if(headers != null) {
            for (int i = 0; i < headers.length; i+=2) {
                this.getResponse().setHeader(headers[i], headers[i+1]);
            }
        }

        try {
            if (bytes != null) { //有byte数组，直接用它输出
                this.getResponse().getOutputStream().write(bytes);
            } else { //没有就从流中读取输出
                IoUtil.copy(is, this.getResponse().getOutputStream());
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            if (this.is != null) {
                IoUtil.close(is);
            }
        }
    }
}
